package com.health.es.generate;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.health.es.entity.data.*;
import com.health.es.entity.data.tool.OpcInfo;
import com.health.es.temp.EsHelper;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.health.es.temp.EsHelper.operations;


/**
 * @author nqlz
 */
@Component
public class IndexInfoGenerate extends GenerateExecute<EsIndexInfo> {


    @Override
    @PostConstruct
    protected void initClasses() {
        addClasses(EsIndexInfo.class);
    }

    @Override
    public void run(Collection<?> objects, Class<EsIndexInfo> tClass) {
        List<EsIndexInfo> tList = objects.parallelStream()
                .map(t -> executeEntity(t, tClass))
                .peek(this::getOpcInfo)
                .collect(Collectors.toList());
        EsHelper.operations.save(tList);
    }

    private final transient List<Class<?>> opcClasses = Arrays.asList(EsOpcPrescription.class, EsIpDoctorAdvice.class,
            EsTestApply.class, EsCkeckApply.class, EsSurgeryApply.class);

    /**
     * 获取opc信息并更新
     *
     * @param t t
     */
    private void getOpcInfo(EsIndexInfo t) {
        EsIndexInfo indexId = EsHelper.searchOne(EsIndexInfo.class, QueryBuilders.matchPhraseQuery("indexId", t.getIndexId()));
        Optional<EsIndexInfo> byId = Optional.ofNullable(indexId);
        if (byId.isPresent()) {
            t.setHasOpc(byId.get().getHasOpc());
        } else {
            updateOpcInfo(t);
        }
    }

    public void updateOpcInfo(EsIndexInfo indexInfo) {
        QueryBuilder baseBuilder = QueryBuilders.termsQuery("hospCodeCard", getCardInfos(indexInfo.getIndexId()));
        boolean hasOpc = Stream.of(EsOpcSeeDoctor.class, EsIpRecord.class)
                .anyMatch(i -> EsHelper.search(i, baseBuilder)
                        .parallelStream()
                        .filter(Objects::nonNull)
                        .peek(this::updateOpcInfo)
                        .anyMatch(OpcInfo::hasOpc)
                );
        indexInfo.setHasOpc(hasOpc ? "1" : "0");
    }

    public Set<String> getCardInfos(String indexId) {
        MatchPhraseQueryBuilder builder = QueryBuilders.matchPhraseQuery("indexId", indexId);
        return EsHelper.getDistinctFields(EsCardInfo.class, "id", builder);
    }

    public <T extends OpcInfo> void updateOpcInfo(T opcInfo) {
        Object hospCodeTreatment1 = ReflectUtil.getFieldValue(opcInfo, "hospCodeTreatment");
        if (StrUtil.isBlankIfStr(hospCodeTreatment1)) {
            return;
        }
        String hospCodeTreatment = hospCodeTreatment1.toString();
        QueryBuilder builder = QueryBuilders.matchPhraseQuery("hospCodeTreatment", hospCodeTreatment);

        Consumer<Class<?>> menuConsumer = tClass -> {
            String value;
            if (EsOpcPrescription.class.equals(tClass)) {
                TermsQueryBuilder noBuilder = QueryBuilders.termsQuery("prescriptionCategory", "02", "03", "04", "99");
                long count = EsHelper.count(EsOpcPrescription.class, w -> w
                        .range(EsOpcPrescription::getDetailCount, r -> r.gt(0))
                        .must(builder).mustNot(noBuilder));
                value = count > 0 ? "1" : "0";
            } else {
                value = EsHelper.count(tClass, builder) > 0 ? "1" : "0";
            }
            opcInfo.setOpcInfo(tClass, value);
        };
        opcClasses.forEach(menuConsumer);
        operations.save(opcInfo);
    }
}
